package cn.hp.config;

import java.util.HashMap;
import java.util.Map;

import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import cn.hp.realm.UserRealm;
import lombok.Data;

@Configuration
@ConditionalOnWebApplication(type=Type.SERVLET)
@ConditionalOnClass(value={SecurityManager.class})
@ConfigurationProperties(prefix="shiro")
@Data
public class ShiroAutoConfiguration {
	
	
	private static final String SHIRO_DIALECT = "ShiroDialect";
	private static final String SHIRO_FILTER = "shiroFilter";
	private String hashAlgorithmName="md5";//加密方式
	private int hashIterations=2;//散列次数
	
	private String loginUrl="/index.html";//默认的登录页面
	private String[] anonUrls;//放行的路径
	private String logOutUrl;//退出登录的路径
	private String[] authcUrls;//拦截的路径
	
	//声明凭证匹配器
	@Bean("credentialsMatcher")
	public HashedCredentialsMatcher hashedCredentialsMatcher(){
		HashedCredentialsMatcher credentialsMatcher=new HashedCredentialsMatcher();
		credentialsMatcher.setHashAlgorithmName(hashAlgorithmName);
		credentialsMatcher.setHashIterations(hashIterations);
		
		return credentialsMatcher;
	}
	
	//声明UserRealm
	@Bean("userRealm")
	public UserRealm userRealm(CredentialsMatcher credentialsMatcher){
		UserRealm userRealm=new UserRealm();
		//注入凭证匹配器
		userRealm.setCredentialsMatcher(credentialsMatcher);
		
		return userRealm;
		
	}
	
	//配置SecurityManager
	@Bean("securityManager")
	public SecurityManager securityManager(UserRealm userRealm){
		DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
		//注入userRealm
		securityManager.setRealm(userRealm);
		
		return securityManager;
	}
	
	
	//配置shiro的过滤器
	@Bean(SHIRO_FILTER)
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
		
		ShiroFilterFactoryBean factoryBean=new ShiroFilterFactoryBean();
		//设置安全管理器
		factoryBean.setSecurityManager(securityManager);
		//设置未登录时要跳转的路径
		factoryBean.setLoginUrl(loginUrl);
		//设置过滤器链
		Map<String, String> filterChainDefinitionMap=new HashMap<String, String>();
		//设置放行的路径
		if(anonUrls !=null && anonUrls.length>0){
			for (String anon : anonUrls) {
				filterChainDefinitionMap.put(anon, "anon");
			}
		}

		//设置登出的路径
		if(logOutUrl !=null){
			filterChainDefinitionMap.put(logOutUrl, "logout");
		}
		
		//设置拦截的路径
		if(authcUrls !=null && authcUrls.length>0){
			for (String authc : authcUrls) {
				filterChainDefinitionMap.put(authc,"authc");
			}
		}
		
		factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		
		return factoryBean;
	}
	
	
	
	//注册shiro的委托过滤器，相当于之前在web.xml里面配置的

	@Bean
	public FilterRegistrationBean<DelegatingFilterProxy> delegatingFilterProxy() {
		FilterRegistrationBean<DelegatingFilterProxy> filterRegistrationBean = new FilterRegistrationBean<DelegatingFilterProxy>();
		DelegatingFilterProxy proxy = new DelegatingFilterProxy();
		proxy.setTargetFilterLifecycle(true);
		proxy.setTargetBeanName(SHIRO_FILTER);
		filterRegistrationBean.setFilter(proxy);
		return filterRegistrationBean;
	}
	
	//加入注解的使用，不加入这个注解不生效--开始
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}

	@Bean
	public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
		advisorAutoProxyCreator.setProxyTargetClass(true);
		return advisorAutoProxyCreator;
	}
	// 加入注解的使用，不加入这个注解不生效--结束
	
	//这里是为了能在html页面引用shiro标签，上面两个函数必须添加，不然会报错

	@Bean(name =SHIRO_DIALECT)
	public ShiroDialect shiroDialect() {
		return new ShiroDialect();
	}

}
